package com.modern.devtools.utils;

import com.modern.devtools.interfaces.SecureStorageService;
import org.springframework.stereotype.Service;

import java.util.prefs.Preferences;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * Secure Storage Service Implementation using Java Preferences API and basic encryption
 * This implementation stores sensitive data in an encrypted format using AES encryption
 */
@Service
public class SecureStorageServiceImpl implements SecureStorageService {
    
    private static final String APP_NAME = "StardustOps";
    private static final String ENCRYPTION_KEY_PREF = "encryption_key";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
    
    private final Preferences prefs;
    private SecretKey encryptionKey;
    
    public SecureStorageServiceImpl() {
        this.prefs = Preferences.userRoot().node(APP_NAME);
        initializeEncryptionKey();
    }
    
    /**
     * Initializes the encryption key, creating a new one if it doesn't exist
     */
    private void initializeEncryptionKey() {
        String keyString = prefs.get(ENCRYPTION_KEY_PREF, null);
        
        if (keyString == null) {
            // Generate a new encryption key
            try {
                KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
                keyGen.init(128); // 128-bit key
                this.encryptionKey = keyGen.generateKey();
                
                // Store the key (base64 encoded) in preferences
                String encodedKey = Base64.getEncoder().encodeToString(this.encryptionKey.getEncoded());
                prefs.put(ENCRYPTION_KEY_PREF, encodedKey);
            } catch (Exception e) {
                throw new RuntimeException("Failed to initialize encryption key", e);
            }
        } else {
            // Load existing encryption key
            byte[] decodedKey = Base64.getDecoder().decode(keyString);
            this.encryptionKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
        }
    }
    
    @Override
    public void storeSecret(String key, String value) {
        if (value == null) {
            prefs.remove(key);
            return;
        }
        
        try {
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
            byte[] encryptedValue = cipher.doFinal(value.getBytes("UTF-8"));
            String encodedValue = Base64.getEncoder().encodeToString(encryptedValue);
            prefs.put(key, encodedValue);
        } catch (Exception e) {
            throw new RuntimeException("Failed to store secret", e);
        }
    }
    
    @Override
    public String retrieveSecret(String key) {
        String encodedValue = prefs.get(key, null);
        if (encodedValue == null) {
            return null;
        }
        
        try {
            byte[] encryptedValue = Base64.getDecoder().decode(encodedValue);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
            byte[] decryptedValue = cipher.doFinal(encryptedValue);
            return new String(decryptedValue, "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("Failed to retrieve secret", e);
        }
    }
    
    @Override
    public void deleteSecret(String key) {
        prefs.remove(key);
    }
    
    @Override
    public boolean hasSecret(String key) {
        return prefs.get(key, null) != null;
    }
}